#include "DatabaseUtil.h"
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlRecord>
#include <QVariant>
#include <QThread>
#include <QDebug>

DatabaseUtil::~DatabaseUtil() {
    QMutexLocker locker(&poolMutex);
    while (!connectionPool.empty()) {
        QString connName = connectionPool.front();
        QSqlDatabase::removeDatabase(connName);
        connectionPool.pop();
    }
}

DatabaseUtil &DatabaseUtil::getInstance() {
    static DatabaseUtil instance;
    return instance;
}

bool DatabaseUtil::init(const QString &configPath) {
    if (!loadConfig(configPath))
        return false;

    host = QString::fromStdString(configJson["databases"]["mysql"]["server"]["host"]);
    port = configJson["databases"]["mysql"]["server"]["port"];
    user = QString::fromStdString(configJson["databases"]["mysql"]["server"]["username"]);
    password = QString::fromStdString(configJson["databases"]["mysql"]["server"]["password"]);
    database = QString::fromStdString(configJson["databases"]["mysql"]["server"]["database"]);

    initPool(10);
    qDebug() << "Database initialized";
    return true;
}

bool DatabaseUtil::loadConfig(const QString &path) {
    QFile file(path);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Failed to open config file:" << path;
        return false;
    }

    QByteArray data = file.readAll();
    configJson = json::parse(data.toStdString(), nullptr, false);
    if (configJson.is_discarded()) {
        qDebug() << "Failed to parse JSON config.";
        return false;
    }
    return true;
}

void DatabaseUtil::initPool(int poolSize) {
    QMutexLocker locker(&poolMutex);
    for (int i = 0; i < poolSize; ++i) {
        QString connName = connectionNamePrefix + QString::number(connectionCounter++);
        QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", connName);
        db.setHostName(host);
        db.setPort(port);
        db.setUserName(user);
        db.setPassword(password);
        db.setDatabaseName(database);

        if (!db.open()) {
            qDebug() << "Failed to open database connection:" << db.lastError().text();
        } else {
            connectionPool.push(connName);
        }
    }
}

QSqlDatabase DatabaseUtil::getConnection() {
    QMutexLocker locker(&poolMutex);
    while (connectionPool.empty()) {
        poolCond.wait(&poolMutex);
    }

    QString connName = connectionPool.front();
    connectionPool.pop();

    // 为当前线程创建新的数据库连接
    QString threadConnName = connName + "_" + QString::number((quintptr) QThread::currentThread());
    QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", threadConnName);
    db.setHostName(host);
    db.setPort(port);
    db.setUserName(user);
    db.setPassword(password);
    db.setDatabaseName(database);

    if (!db.open()) {
        qDebug() << "Failed to open database connection:" << db.lastError().text();
    }

    return db;
}

void DatabaseUtil::releaseConnection(QSqlDatabase conn) {
    if (conn.isOpen()) {
        conn.close();
    }
    QString connName = conn.connectionName();
    QSqlDatabase::removeDatabase(connName);

    QMutexLocker locker(&poolMutex);
    // 只保留原始连接名（不包含线程ID部分）
    QString baseConnName = connName.split("_").first();
    connectionPool.push(baseConnName);
    poolCond.wakeOne();
}

json DatabaseUtil::executeQuery(const QString &query, const QVariantList &params) {
    QSqlDatabase db = getConnection();
    QSqlQuery q(db);
    json result = json::array();

    q.prepare(query);
    // 自动绑定参数（按顺序对应 ?）
    for (const QVariant &param: params) {
        q.addBindValue(param);
    }

    if (q.exec()) {
        QSqlRecord rec = q.record();
        while (q.next()) {
            json row;
            for (int i = 0; i < rec.count(); ++i) {
                QString colName = rec.fieldName(i);
                QVariant value = q.value(i);

                // 根据字段类型进行转换
                if (value.type() == QVariant::Int || value.type() == QVariant::LongLong) {
                    row[colName.toStdString()] = value.toLongLong();
                } else if (value.type() == QVariant::Double) {
                    row[colName.toStdString()] = value.toDouble();
                } else if (value.type() == QVariant::Bool) {
                    row[colName.toStdString()] = value.toBool();
                } else {
                    row[colName.toStdString()] = value.toString().toStdString();
                }
            }
            result.push_back(row);
        }
    } else {
        qDebug() << "Query failed:" << q.lastError().text();
    }

    releaseConnection(db);
    return result;
}

int DatabaseUtil::executeUpdate(const QString &query, const QVariantList &params) {
    QSqlDatabase db = getConnection();
    QSqlQuery q(db);

    q.prepare(query);
    // 自动绑定参数（按顺序对应 ?）
    for (const QVariant &param: params) {
        q.addBindValue(param);
    }

    int affected = 0;

    if (!q.exec()) {
        qDebug() << "Update failed:" << q.lastError().text();
    } else {
        affected = q.numRowsAffected();
    }

    releaseConnection(db);
    return affected;
}
